home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C# & Game Programming - A…er's Guide (2nd Edition)
/
Buono 2nd Ed.iso
/
Chapter3
/
AsteroidMiner
/
AsteroidMiner DirectX9
/
AsteroidMinerDX.cs
< prev
next >
Wrap
Text File
|
2004-09-02
|
32KB
|
777 lines
/* AsteroidMiner v2.1 DirectX Edition - by Salvatore A. Buono */
using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO; // for file read/write
using Microsoft.DirectX;
using Microsoft.DirectX.DirectDraw;
using Microsoft.DirectX.DirectSound;
using Buffer = Microsoft.DirectX.DirectSound.SecondaryBuffer;
using Microsoft.DirectX.DirectInput;
using GameClasses; // Our common utility class
namespace Games {
public class AsteroidMiner : System.Windows.Forms.Form {
// DirectDraw
private Microsoft.DirectX.DirectDraw.Device draw = null;
private Surface primary = null;
private Surface buffer = null;
private Surface[] PlayerLDraw = new Surface[9];
private Surface[] PlayerRDraw = new Surface[9];
private Surface[] ExhaustDraw = new Surface[9];
private Rectangle destination = new Rectangle();
// DirectSound
private Microsoft.DirectX.DirectSound.Device sound = null;
private SecondaryBuffer SoundBuffer = null;
// DirectInput
private Microsoft.DirectX.DirectInput.Device keyboard = null;
private Microsoft.DirectX.DirectInput.Device joystick = null;
public JoystickState State = new JoystickState();
private System.Windows.Forms.Timer Joystick;
private System.Windows.Forms.Timer Keyboard;
// Constants
const int SCALE = 25;
const string MEDIA_ROOT = @".\media\";
const int TIMER_BASE = 40; // in millis.
const int MAX_STARS = 20; // # of stars
const int MAX_ASTEROIDS = 4; // # of asteroids (if on)
const int MAX_MISSILES = 4; // # of missiles/ship
const int MISSILE_LIFE = 50; // 40 ticks
const int THRUSTER_LIFE = 10; // 10 ticks
const int ASTEROID_SPEED = 10;// how much they move
const int GRAVITY_SPEED = 75; // how often gravity affects you
const int GRAVITY_EFFECT = 5; // how much it effects you
const int DEFAULT_SPEED = 5; // default game speed
const int NUM_LIVES = 5; // determines when the game is over
const int SCORE_ASTEROID = 10; // 10 points for hitting an asteroid
// Member fields -- UI elements
private System.Windows.Forms.MainMenu mainMenu1;
private System.Windows.Forms.MenuItem menuItem1;
private System.ComponentModel.Container components = null;
// Member fields
GameState gameState; // Holds state information
PlayerImageArray player;
AnimatedImage[] exhaustImages;
private Surface[] PlayerMissilesDraw = new Surface[MAX_MISSILES];
AnimatedImage[] playerMissiles;
private Surface[] AsteroidDraw = new Surface[MAX_ASTEROIDS];
AnimatedImage[] asteroids;
Point[] stars; // background star field
private Surface[] StarsDraw = new Surface[MAX_STARS];
GameTimer timer; // Event timer to control all animation
TimedEvent p1Event; // The player event, for easy reference
int HighScore = 0; // Game's top score loads from file
int p1LastDirection = 0;
// Main entry-point function
[STAThread] static void Main() {
Application.Run(new AsteroidMiner());
}
#region Set-up & Initialization
// Default constructor
public AsteroidMiner() {
InitializeComponent();
// DirectDraw
draw = new Microsoft.DirectX.DirectDraw.Device();
draw.SetCooperativeLevel(this,
Microsoft.DirectX.DirectDraw.CooperativeLevelFlags.FullscreenExclusiveAllowModex);
draw.SetDisplayMode(640, 480, 32, 0, false);
CreateSurfaces();
// DirectSound
sound = new Microsoft.DirectX.DirectSound.Device();
sound.SetCooperativeLevel(this, CooperativeLevel.Priority);
gameState = new GameState();
// Set up timer & timed events
timer = new GameTimer(TIMER_BASE);
TimedEvent newEvent;
// Initialize the two player objects
player = new PlayerImageArray(9);
player.constraintBox = this.ClientRectangle;
// player thruster event
newEvent = new TimedEvent(THRUSTER_LIFE,
new TickHandler(PlayerThrust));
newEvent.payload = player;
timer.addEvent(newEvent, 1, "player");
p1Event = newEvent;
// Initialize exhaust images
exhaustImages = new AnimatedImage[9];
for (int i = 0; i < 9; i ++) {
exhaustImages[i] = new AnimatedImage(0, 0);
exhaustImages[i].RescaleImage(SCALE / 2, SCALE / 2);
}
// Set correct image offsets
exhaustImages[1].imageOffsetX = 14;
exhaustImages[1].imageOffsetY = -5;
exhaustImages[2].imageOffsetX = 9;
exhaustImages[2].imageOffsetY = -9;
exhaustImages[3].imageOffsetX = 0;
exhaustImages[3].imageOffsetY = -6;
exhaustImages[4].imageOffsetX = -8;
exhaustImages[4].imageOffsetY = 6;
exhaustImages[5].imageOffsetX = 1;
exhaustImages[5].imageOffsetY = 17;
exhaustImages[6].imageOffsetX = 8;
exhaustImages[6].imageOffsetY = 20;
exhaustImages[7].imageOffsetX = 11;
exhaustImages[7].imageOffsetY = 17;
exhaustImages[8].imageOffsetX = 20;
exhaustImages[8].imageOffsetY = 6;
// Initialize the background stars
Random rnd = new Random();
stars = new Point[MAX_STARS];
for (int i = 0; i < MAX_STARS; i++)
stars[i] = new Point(rnd.Next(ClientSize.Width), rnd.Next(ClientSize.Height));
// Initialize player's missiles
playerMissiles = new AnimatedImage[MAX_MISSILES];
for (int i = 0; i < MAX_MISSILES; i++) {
playerMissiles[i] = new AnimatedImage(0, 0);
playerMissiles[i].owner = player;
playerMissiles[i].constraintBox = this.ClientRectangle;
playerMissiles[i].RescaleImage(SCALE / 5, SCALE / 5);
// Set up timer & events
newEvent = new TimedEvent(MISSILE_LIFE,
new TickHandler(MoveMissile));
newEvent.payload = playerMissiles[i];
timer.addEvent(newEvent, 1, "playerMissile" + i);
}
// Initialize the asteroids
asteroids = new AnimatedImage[MAX_ASTEROIDS];
for (int i = 0; i < MAX_ASTEROIDS; i++) {
// Note, there are only 4 image positions so strange
// things happen when MAX_ASTEROIDS > 4
asteroids[i] = new AnimatedImage((i % 2 == 1) ? 3 * SCALE :
20 * SCALE, (i < 2 ? 3 * SCALE : 12 * SCALE));
asteroids[i].direction = rnd.Next(1, 8);
asteroids[i].constraintBox = this.ClientRectangle;
asteroids[i].RescaleImage(2 * SCALE, 2 * SCALE);
newEvent = new TimedEvent(new TickHandler(MoveAsteroids));
newEvent.payload = asteroids[i];
timer.addEvent(newEvent, ASTEROID_SPEED, "asteroid" + i);
newEvent.isActive = true;
}
newEvent = new TimedEvent(new TickHandler(Gravity));
newEvent.isActive = true;
timer.addEvent(newEvent, GRAVITY_SPEED, "");
// Call Invalidate() every tick
newEvent = new TimedEvent(new TickHandler(ScreenRefresh));
timer.addEvent(newEvent, 1, "invalidate");
newEvent.isActive = true;
}
#region DirectDraw CreateSurfaces
private void CreateSurfaces() {
SurfaceDescription description = new SurfaceDescription();
description.SurfaceCaps.PrimarySurface = true;
description.SurfaceCaps.Flip = true;
description.SurfaceCaps.Complex = true;
description.BackBufferCount = 1;
primary = new Surface(description, draw);
SurfaceCaps caps = new SurfaceCaps();
caps.BackBuffer = true;
buffer = primary.GetAttachedSurface(caps);
description.Clear();
try {
for(int i = 1; i < 9; i++) {
PlayerLDraw[i] = new Surface(MEDIA_ROOT + "Ship1-" + i + ".bmp", description, draw);
PlayerRDraw[i] = new Surface(MEDIA_ROOT + "Ship2-" + i + ".bmp", description, draw);
ExhaustDraw[i] = new Surface(MEDIA_ROOT + "Exhaust" + i + ".bmp", description, draw);
}
for(int i = 0; i < MAX_MISSILES; i++) {
PlayerMissilesDraw[i] = new Surface(MEDIA_ROOT + "Weapon1.bmp", description, draw);
}
for(int i = 0; i < MAX_STARS; i++) {
StarsDraw[i] = new Surface(MEDIA_ROOT + "FireBall.bmp", description, draw);}
PlayerLDraw[0] = new Surface(MEDIA_ROOT + "FireBall.bmp", description, draw);
PlayerRDraw[0] = new Surface(MEDIA_ROOT + "FireBall.bmp", description, draw);
for(int i = 0; i < MAX_ASTEROIDS; i++) {
AsteroidDraw[i] = new Surface(MEDIA_ROOT + "Asteroid" + i + ".bmp", description, draw);}
}
catch (FileNotFoundException ex) {
MessageBox.Show("Please check that the following file exists:\n\n" +
ex.Message + "\n\nCorrect the file referenced in the config file.",
"File Not Found!");
Application.Exit();}
catch{Application.Exit();}
}
#endregion
// (re) Sets positional data, scores, and other game data
public void Setup() {
gameState.currentState = GameState.State.Started;
gameState.currentSpeed = DEFAULT_SPEED;
player.imagePosX = 12 * SCALE - (player.imageWidth >> 1);
player.imagePosY = 8 * SCALE;
if (player.score > HighScore)
SaveHighScore(player.score);
HighScore = LoadHighScore();
if(HighScore < player.score) {
HighScore = player.score;}
player.score = 0;
player.deaths = 0;
player.isActive = true;
player.direction = AnimatedImage.NORTH;
for (int i = 0; i < MAX_MISSILES; i++) {
playerMissiles[i].isActive = false;
}
for (int i = 0; i < MAX_ASTEROIDS; i++) {
asteroids[i].RescaleImage(2 * SCALE, 2 * SCALE);
asteroids[i].isActive = true;
}
timer.Start();
}
// Form's initialize method - we initialize all form related items
private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
this.mainMenu1 = new System.Windows.Forms.MainMenu();
this.menuItem1 = new System.Windows.Forms.MenuItem();
//
// mainMenu1
//
this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItem1});
//
// menuItem1
//
this.menuItem1.Index = 0;
this.menuItem1.Text = "Asteroid Miner";
this.menuItem1.Click += new System.EventHandler(this.SinglePlayer_Click);
//
// AsteroidMiner
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.BackColor = System.Drawing.Color.Black;
this.ClientSize = new System.Drawing.Size(600, 400);
this.Menu = this.mainMenu1;
this.Name = "AsteroidMiner";
this.Text = "Asteroid Miner";
this.Load += new System.EventHandler(this.AsteroidMiner_Load);
this.Joystick = new System.Windows.Forms.Timer(this.components);
this.Joystick.Tick += new System.EventHandler(this.JoyStick_Tick);
this.Keyboard = new System.Windows.Forms.Timer(this.components);
this.Keyboard.Tick += new System.EventHandler(this.Keyboard_Tick);
}
#endregion
#region Game-play functions
// Start up the player's thrusters
public void EngageThrusters(Player player) {
if (player.isActive) {
if (player == player)
p1Event.Reset(); // reset the timer from now
try {
SoundBuffer = new SecondaryBuffer(MEDIA_ROOT + "Thrust.wav", sound);
SoundBuffer.Play(0, BufferPlayFlags.Default);}
catch{Utils.PlaySound(MEDIA_ROOT + "Thrust.WAV");}
}
return;
}
// Fire a missile (if any available) from the given player
public void FireMissile(Player player, AnimatedImage[] missiles) {
if (!player.isActive)
return;
for (int i = 0; i < MAX_MISSILES; i++) {
// shoot the first missile that's not already out there!
if (!missiles[i].isActive) {
// set missiles properties so that it will get
// properly animated
missiles[i].isActive = true;
missiles[i].direction = player.direction;
missiles[i].imagePosX = player.imagePosX;
missiles[i].imagePosY = player.imagePosY;
TimedEvent missileEvent = timer.getEvent
("playerMissile" + i);
missileEvent.Reset();
try {
SoundBuffer = new SecondaryBuffer(MEDIA_ROOT + "Fire.wav", sound);
SoundBuffer.Play(0, BufferPlayFlags.Default);}
catch{Utils.PlaySound(MEDIA_ROOT + "Fire.WAV");}
break;
}
}
}
public void ExertGravitationalPull(Player player) {
if (player.imagePosX != ClientSize.Width >> 1)
player.imagePosX += (player.imagePosX >
(ClientSize.Width >> 1)) ? -GRAVITY_EFFECT : GRAVITY_EFFECT;
if (player.imagePosY != ClientSize.Height >> 1)
player.imagePosY += (player.imagePosY >
(ClientSize.Height >> 1)) ? -GRAVITY_EFFECT : GRAVITY_EFFECT;
}
#endregion
#region Collision Detection Routines
// Ships can run into the asteroids and missiles.
// We'll assume that the missiles will detect their collisions
// so we only have to worry about the others.
public bool CheckShipCollision(Player player) {
Player opponent = player;
// Asteroid collision?
for (int i = 0; i < MAX_ASTEROIDS; i++) {
if (asteroids[i].isActive) {
if (asteroids[i].Intersects(player)) {
ShipCollided(player);
return true;
}
}
}
return false;
}
// Asteroids can run into ships & missiles. We'll assume that
// missiles will detect their collisions themselves since they
// update frequently.
public bool CheckAsteroidCollision() {
for (int i = 0; i < MAX_ASTEROIDS; i++) {
if (asteroids[i].isActive) {
if (asteroids[i].Intersects(player)) {
ShipCollided(player);
return true;
}
}
}
return false;
}
// Missiles can only run into asteroids.
public bool CheckMissileCollision(AnimatedImage missile) {
if (missile.isActive) {
for (int i = 0; i < MAX_ASTEROIDS; i++) {
if (missile.Intersects(asteroids[i])) {
AsteroidCollided(asteroids[i]);
missile.isActive = false;
try {
SoundBuffer = new SecondaryBuffer(MEDIA_ROOT + "Hit.wav", sound);
SoundBuffer.Play(0, BufferPlayFlags.Default);}
catch{Utils.PlaySound(MEDIA_ROOT + "Hit.WAV");}
return true;
}
}
}
return false; // Must not have hit anything!
}
// The ship ran into something! Add to the death count and
// end the game if we're out of lives.
public void ShipCollided(Player victim) {
if (!victim.isActive)
return; // He's already dead!
victim.isActive = false;
victim.direction = 0; // index of our explosion image
try {
SoundBuffer = new SecondaryBuffer(MEDIA_ROOT + "Hit.wav", sound);
SoundBuffer.Play(0, BufferPlayFlags.Default);}
catch{Utils.PlaySound(MEDIA_ROOT + "Hit.WAV");}
victim.deaths++;
if(victim.deaths >= NUM_LIVES) {
gameState.currentState = GameState.State.Stopped;
if (victim.score > HighScore) {
SaveHighScore(victim.score);
}
Application.Exit();
}
}
// The asteroid was hit! Cycle through its different scaled
// display & increment the player's score.
public void AsteroidCollided(AnimatedImage victim) {
int scaleFactor = (victim.imageWidth <= (SCALE / 2)) ?
SCALE * 2 : victim.imageWidth / 2;
victim.RescaleImage(scaleFactor, scaleFactor);
player.score += SCORE_ASTEROID;
}
#endregion
#region OnPaint
protected override void OnPaint(PaintEventArgs e) {
// Write start-up text if game is stopped
if (gameState.currentState == GameState.State.Stopped) {
Brush YellowBrush = Brushes.Yellow;
Font LargeAlgerianFont = new Font("Algerian", 24);
Font MidAlgerianFont = new Font("Algerian", 18);
Graphics g = e.Graphics; // Screen's graphics object
g.DrawString("C# and Game Programming", LargeAlgerianFont, YellowBrush, 2 * SCALE, SCALE);
g.DrawString("A Beginner's Guide", LargeAlgerianFont, YellowBrush, 9 * SCALE, 5 * SCALE);
g.DrawString("By Salvatore A. Buono", MidAlgerianFont, YellowBrush, 2 * SCALE, 14 * SCALE);
} else {
buffer.ColorFill(Color.Black);
// Draw the scores
buffer.ForeColor = Color.Blue;
if(player.score < HighScore) {
buffer.DrawText(4 * SCALE, 2*SCALE, HighScore.ToString(), false);}
else {
buffer.DrawText(4 * SCALE, 2*SCALE, player.score.ToString(), false);}
buffer.DrawText(16 * SCALE, 2*SCALE, player.score.ToString(), false);
// Draw the stars
for(int i = 0; i < MAX_STARS; i++) {
try {
destination = new Rectangle(stars[i].X, stars[i].Y, 10, 10);
buffer.Draw(destination, StarsDraw[i], DrawFlags.Wait);}
catch(SurfaceLostException){CreateSurfaces();}
catch{}
}
// Draw player 1 & its appropriate exhaust
try {
destination = new Rectangle(player.imagePosX, player.imagePosY, SCALE, SCALE);
buffer.Draw(destination, PlayerLDraw[player.direction], DrawFlags.Wait);}
catch(SurfaceLostException){CreateSurfaces();}
catch{}
if (p1Event.isActive) {
try {
int X = player.imagePosX + exhaustImages[player.direction].imageOffsetX;
int Y = player.imagePosY + exhaustImages[player.direction].imageOffsetY;
destination = new Rectangle(X, Y, SCALE/2, SCALE/2);
buffer.Draw(destination, ExhaustDraw[player.direction], DrawFlags.Wait);}
catch(SurfaceLostException){CreateSurfaces();}
catch{}
}
// Draw missiles
for (int i = 0; i < MAX_MISSILES; i ++) {
if (playerMissiles[i].isActive)
try {
destination = new Rectangle(playerMissiles[i].imagePosX,
playerMissiles[i].imagePosY, SCALE/5, SCALE/5);
buffer.Draw(destination, PlayerMissilesDraw[i], DrawFlags.Wait);}
catch(SurfaceLostException){CreateSurfaces();}
catch{}
}
// Draw asteroids
for (int i = 0; i < MAX_ASTEROIDS; i++) {
try {
destination = new Rectangle(asteroids[i].imagePosX,
asteroids[i].imagePosY, asteroids[i].imageWidth, asteroids[i].imageHeight);
buffer.Draw(destination, AsteroidDraw[i], DrawFlags.Wait);}
catch(SurfaceLostException){CreateSurfaces();}
catch{}
}
primary.Flip(buffer, FlipFlags.DoNotWait);
}
buffer.Dispose();
}
#endregion
#region Keyboard_Tick
// Capture keyboard input for player control
private void Keyboard_Tick(object sender, System.EventArgs e) {
Microsoft.DirectX.DirectXException.IgnoreExceptions ();
if (gameState.currentState != GameState.State.Started)
return;
keyboard = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
keyboard.Properties.BufferSize = 8;
keyboard.Acquire();
KeyboardState state = keyboard.GetCurrentKeyboardState();
for (Key k = Key.Escape; k <= Key.MediaSelect; k++) {
if (state[k] && (k == Key.Space || k == Key.NumPad0)) {
FireMissile(player, playerMissiles);}
else if (state[k] && k == Key.Up) {
p1LastDirection = player.direction;
EngageThrusters(player);}
else if (state[k] && k == Key.Left) {
if (player.isActive)
player.RotateDirection(1);}
else if (state[k] && k == Key.Right) {
if (player.isActive)
player.RotateDirection(-1);}
else if (state[k] && k == Key.Down) {
if (!player.isActive)
player.isActive = true;
player.RandomizePosition();}
else if (state[k] && k == Key.Escape) {
Application.Exit();}
}
}
#endregion
#region Joystick
private void JoyStick_Tick(object sender, System.EventArgs e) {
Microsoft.DirectX.DirectXException.IgnoreExceptions ();
foreach (DeviceInstance instance in Manager.GetDevices(DeviceClass.GameControl,
EnumDevicesFlags.AttachedOnly)) {
joystick = new Microsoft.DirectX.DirectInput.Device(instance.InstanceGuid);
break;}
if(joystick == null) {return;}
joystick.SetDataFormat(DeviceDataFormat.Joystick);
foreach (DeviceObjectInstance d in joystick.Objects) {
if ((0 != (d.ObjectId & (int)DeviceObjectTypeFlags.Axis))) {
joystick.Properties.SetRange(ParameterHow.ById,
d.ObjectId, new InputRange(-1000, 1000));}
}
joystick.SetCooperativeLevel(this, Microsoft.DirectX.DirectInput.CooperativeLevelFlags.Background | Microsoft.DirectX.DirectInput.CooperativeLevelFlags.NonExclusive);
joystick.Properties.AxisModeAbsolute = true;
joystick.Acquire();
joystick.Poll();
State = joystick.CurrentJoystickState;
if(-600 > State.Y) {
if (!player.isActive)
player.isActive = true;
player.RandomizePosition();}
if(player.isActive == true) {
if(-400 < State.X && -600 > State.Y) {
player.RotateDirection(1);}
else if(-500 > State.X && -600 > State.Y) {
player.RotateDirection(-1);}
else if(-400 < State.X && -500 < State.Y) {
player.RotateDirection(1);}
else if(-500 > State.X && -500 < State.Y) {
player.RotateDirection(-1);}
else if(-400 < State.X) {
player.RotateDirection(-1);}
else if(-500 > State.X) {
player.RotateDirection(1);}
else if(-500 < State.Y) {
p1LastDirection = player.direction;
EngageThrusters(player);}
byte[] buttons = State.GetButtons(); {
foreach (byte b in buttons) {
if (0 != (b & 0x80)) {
for(int i = 0; i < MAX_MISSILES; i++) {
if(playerMissiles[i].isActive == false) {
FireMissile(player, playerMissiles);
break;}
}
}
}
}
}
}
#endregion
#region TimedEvent Tick Handlers
// Implements the player's thruster push. Called repetitively until
// the timer counts down to 0.
public void PlayerThrust(TimedEvent e, Object obj) {
if (gameState.currentState == GameState.State.Stopped) {
e.isActive = false;
return;
}
Player player = (Player) obj;
int tempDir = player.direction;
player.direction = p1LastDirection;
player.Animate();
player.Animate();
player.direction = tempDir;
player.WrapInBox();
CheckShipCollision(player);
}
// Implements the missile's movement. Called automatically until
// the timer counts down to 0.
public void MoveMissile(TimedEvent e, Object obj) {
if (gameState.currentState == GameState.State.Stopped) {
e.isActive = false;
return;
}
// Get a proper missile object from the event
AnimatedImage missile = (AnimatedImage) obj;
for(int i = 0; i < gameState.currentSpeed; i++) {
missile.Animate();
missile.WrapInBox();
// See if we hit anything!
CheckMissileCollision(missile);
}
// disable the missile so it can be fired again
if (e.tickCounter <= 1)
missile.isActive = false;
}
// Implements the asteroid's random movement. This is called
// continously throughout the game.
public void MoveAsteroids(TimedEvent e, Object obj) {
if (gameState.currentState == GameState.State.Stopped) {
e.isActive = false;
return;
}
Random rnd = new Random();
for(int i = 0; i < MAX_ASTEROIDS; i++) {
if (rnd.Next(10) > 7) // Change the direction ~70% of the time
asteroids[i].direction = rnd.Next(1, 8);
asteroids[i].Animate();
asteroids[i].WrapInBox();
CheckAsteroidCollision();
}
}
// Implements the gravity (from an unseen field -- that only
// affects ships -- located at the center of the screen).
public void Gravity(TimedEvent e, Object obj) {
if (gameState.currentState == GameState.State.Stopped) {
e.isActive = false;
return;
}
if (player.isActive){ // Doesn't pull "dead" ships
ExertGravitationalPull(player);
CheckShipCollision(player);
}
try {
SoundBuffer = new SecondaryBuffer(MEDIA_ROOT + "Gravity.wav", sound);
SoundBuffer.Play(0, BufferPlayFlags.Default);}
catch{Utils.PlaySound(MEDIA_ROOT + "Gravity.WAV");}
}
// Regular refresh function. The screen will redraw every tick.
public void ScreenRefresh(TimedEvent e, Object obj) {Invalidate();}
#endregion
#region Menu Click Handler
private void SinglePlayer_Click(object sender, System.EventArgs e) {
gameState.currentMode = GameState.Mode.SinglePlayer;
Setup();
}
#endregion
#region File Read/Write
// Utility function to read the high score from a file
public int LoadHighScore() {
StreamReader file;
string strTemp = "";
int score = 0;
try {
file = new StreamReader(@".\HighScore.txt");
for (int i = 0; i < 4; i++)
strTemp = file.ReadLine();
score = int.Parse(strTemp.Substring(0, strTemp.IndexOf("\t")));
file.Close();
} catch (Exception e) {Console.WriteLine(e);}
return score;
}
// Utility function to write the high score from a file
public void SaveHighScore(int score) {
StreamWriter file;
try {
file = new StreamWriter(@".\HighScore.txt");
file.WriteLine("Asteroid Miner High Scores");
file.WriteLine("--------------------------");
file.WriteLine();
file.WriteLine(score + "\t" + DateTime.Now);
file.Flush();
file.Close();
} catch (Exception e) {Console.WriteLine(e);}
}
#endregion
// Clean exit function
public void ExitApplication() {
Application.Exit();
}
// The default Invalidate clears the entire screen creating a very
// undesireable flicker. This override allows the paint method to
// control it's redraw.
public new void Invalidate() {
OnPaint(new PaintEventArgs(Graphics.FromHwnd(this.Handle),
new Rectangle(new Point(0, 0), this.Size)));
}
// The system occasionally also calls OnPaintBackground which will
// mean the screen will be cleared, painted with the background
// color, then repainted. This is another cause of flicker, so we
// just override it and tell it not to do anything!
protected override void OnPaintBackground(PaintEventArgs e) {
// Do nothing!
}
private void AsteroidMiner_Load(object sender, System.EventArgs e) {
// DirectInput
Joystick.Start();
Keyboard.Start();
}
}
}